  /*
  ** Danny newman
    Erik Rotaru
    Aaron Hill
    3/9/10
    Project 2 CS457
    
    Server
  */

  #include <stdio.h>
  #include<iostream>
  #include <stdlib.h>
  #include <unistd.h>
  #include <errno.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <string.h>
  #include <netdb.h>
  #include <arpa/inet.h>
  #include <sys/wait.h>
  #include <signal.h>
  #include <pthread.h>

  #include "awget.h"
 
  #define BACKLOG 10     // how many pending connections queue will hold
  #define MAXDATASIZE 100 // max number of bytes we can get at once 
  #define HOSTNAMESIZE 100 // max size for hostname

  using namespace std;
  
  
  FILE* getFile(char* fileName);
  int getRandomNumber(int entries);
  int openNewTCPsocket(char * hostname, char * port);
  int initializeNewConnection(char* hostname, char* port);
  void printByteArray(byte* byteArray);
  int extractIPAddress(struct ipPortPair * nextSS, byte * byteArray, int randomSS);
  void extractPort(struct ipPortPair *nextSS, byte * byteArray, int startIndex);
  void decrementSSNum(byte * byteArray);
  void removeNextSS(byte byteArray[], int endIndex, int ipPortLength, int arrayLength);
  
  int requestFile(char *hostname, int port, byte byteArray[], int size);
  void receiveFile(int sockfd, byte * byteArray, int totalSize);
  void returnFile(int sockfd, byte * fileByteArray, int urlFileSize);
  void printFileByteArray(byte* byteArray);
  void printChainList(byte * byteArray, int totalSize, int URL_LEN);
  void printHostIPAddress();
  void printRequestedFile(byte *byteArray);
 
  
  typedef unsigned char byte;
  typedef unsigned short packLength;


  static int debug = 0;

  void sigchld_handler(int s)   // The Child's Signal Handler 
  {
	  s=-1;
      while(waitpid(s, NULL, WNOHANG) > 0);   //  as children die, we ensure they don't turn to Zombies
				  // by catching their returns;
  }

  // get sockaddr, IPv4 or IPv6:
  void *get_in_addr(struct sockaddr *sa) 
  {
      if (sa->sa_family == AF_INET) {    // if the type is IPV4
	  return &(((struct sockaddr_in*)sa)->sin_addr);   // return this
      }
      return &(((struct sockaddr_in6*)sa)->sin6_addr);   // (Implied) ELSE: its Ipv6 
  }



  /**Threads listen on the passed file descriptor and wait for incoming data */
  void * listenAndWait(void *new_fd){
	  long requestSockfd;
	  requestSockfd = (long)new_fd;
	  int numbytes = 0;

	  packLength URL_LEN =0;
	  packLength filesize = 0;
	  
	  //receive the first 4 bytes of packet for filesize and URL length
	  byte ul[4];
	  if( (numbytes = recv(requestSockfd, ul, 2, 0))){
		  URL_LEN = (packLength)(((ul[1]<<8)&0x0000FF00)+ul[0]);
	  }
	  else{
	  	if(debug)printf("data not received");
	  }
	  if((numbytes = recv(requestSockfd, ul+2, 2, 0))){
		  filesize = (packLength)(((ul[3]<<8)&0x0000FF00)+ul[2]);
	  }
	  else{
	  	if(debug)printf("data not received");
	  }
	  
	  
	  int totalSize = URL_LEN + filesize+4;
	  
	  byte byteArray[totalSize];
	  //store [URL_LEN][filesize] in first 4 bytes of packet
	  byteArray[0] = ul[0];
	  byteArray[1] = ul[1];
	  byteArray[2] = ul[2];
	  byteArray[3] = ul[3];
		  
	  int offset = 4;
	  int totalRec = totalSize-4;
	  //receive the URL and file into the byteArray
	  while( (numbytes = recv(requestSockfd, byteArray+offset, totalRec, 0)) > 0 ) {
		  offset += numbytes;
		  totalRec -= numbytes;
		  //printf("received %d bytes\n",numbytes);
		  if(numbytes == (totalSize-4))break;
	  }
	  
	  if(debug){
		printf("\nThis is what the stepping stone got\n");
		printByteArray(byteArray);
	  }
	  
	  printRequestedFile(byteArray);
	  //get the # of ss left. If 0, then wget...
	  char ssNumString[10];
	  int ssNum;
	  int index = 0;
	  offset = 4;
	  while((char)byteArray[URL_LEN+offset] == ' ' || (char)byteArray[URL_LEN+offset] == '\t'){
	    ++offset;
	  }
	  while((char)byteArray[URL_LEN+offset] != ' ' && (char)byteArray[URL_LEN+offset] != '\t' 
	    && (char)byteArray[URL_LEN+offset] != '\n' && (char)byteArray[URL_LEN+offset] != '\0' && (URL_LEN+offset)<totalSize){
		  ssNumString[index++] = (char)byteArray[URL_LEN+offset];
		  ++offset;
		  if(offset > 9){
		     if(debug)printf("SS Number was too large!!\n");
			 exit(1);
		   }
	  }
	  ssNum = atoi(ssNumString);
	  
	  if(ssNum <0){
		if(debug)printf("SS Number was less than 0! Setting SS Number to 0...\n");
		ssNum = 0;
	  }
	  if(ssNum == 0) {
		 if(debug)printf("\nThis is the last ss: %c, so WGET the file\n", ssNum);
		 printf("  chainlist is empty\n");
		 char website[URL_LEN+1];
		  for(int i=4;i<URL_LEN+4;i++){
		  //The URL
			 website[i-4] = byteArray[i];
			 if(debug > 1)printf("%c",(char)byteArray[i]);
		  }
		  website[URL_LEN] = '\0';
	  
	      char* fileAddress = (char*)malloc(sizeof(char)*1000);
		  strcpy(fileAddress, website);//File address that we are going to recieve
		  printf("  issueing wget for %s\n..\n", website);
		  FILE * urlFile = getFile(fileAddress);
		  printf("  File received\n");
		int urlFileSize;
		//find the size of the file and put in filesize
		fseek( urlFile, 0L, SEEK_END);
		urlFileSize = (int)ftell(urlFile);
		
		//put file marker at beginning of file
		fseek(urlFile, 0L, SEEK_SET);
		
		int totalByteArraySize = urlFileSize +4;
		byte fileByteArray[totalByteArraySize];
		//insert file size into first 2 bytes of fileByteArray
		fileByteArray[0] = urlFileSize & 0x000000FF;
		fileByteArray[1] = (urlFileSize & 0x0000FF00) >> 8;
		fileByteArray[2] = (urlFileSize & 0x00FF0000) >> 16;
		fileByteArray[3] = (urlFileSize & 0xFF000000) >> 24;
		//insert the urlFile into the rest of the fileByteArray
		
		if(debug > 1)printf("converting file into byteArray: %d\n", totalByteArraySize);
		int index = 4;
		char c;
		while((c = getc(urlFile)) != EOF){	
			fileByteArray[index++] = (byte)c;
		}
		//Close and delete the file
		fclose(urlFile);
		free(fileAddress);
	  	system("rm requested_file");
		printf("  Relaying file...\n");
		returnFile(requestSockfd, fileByteArray, totalByteArraySize);
	  }
	  else {
	    if(debug)printf("\nNot the last ss: %d\n", ssNum);
	  
	  
	    //if not lastSS, then randomly select the next ss.
	    int randomSS = getRandomNumber(ssNum);

	    struct ipPortPair *nextSS = (struct ipPortPair *) malloc (sizeof(struct ipPortPair));
	    //if not \n then keep going. If \n then (if ss == 0 get \n's index, 
	    //else decrement ss and keep going.
		
		
		printChainList(byteArray, totalSize, URL_LEN);
		
		if(debug > 1){
			printf("extract ip %d\n", randomSS);
			printByteArray(byteArray);
		}
		int startIndex = extractIPAddress(nextSS, byteArray, randomSS);
		extractPort(nextSS, byteArray, startIndex);
		
		decrementSSNum(byteArray);
	    
		
		
		/* calculate new byte array */
		int byteArraySize = totalSize;
		int newFileLength = filesize;
		for(int i=0;i<URL_LEN+4;i++){
			if((char)byteArray[i] == ' ')
				byteArraySize--;
		}
		
		for(int i=URL_LEN+4;i<totalSize;i++){
			if((char)byteArray[i] == ' '){
				byteArraySize--;
				newFileLength--;
			}
		}
		
		byte newByteArray[byteArraySize];
			
		//put the byteArray into a new, smaller byte array without the spaces
		int index = 0;
		for(int i=0;i<byteArraySize;i++){
			while((char)byteArray[index] == ' '){++index;}
			if(index >= totalSize) break;
			newByteArray[i] = byteArray[index++];
		}
		newByteArray[2] = newFileLength & 0x00FF;
		newByteArray[3] = (newFileLength & 0xFF00) >> 8;
		
		if(debug > 1){printf("new byte Array:\n"); printByteArray(newByteArray);}
		
		printf("  next SS is %s, %d\n",nextSS->ip, nextSS->port);
		/*send the byte array to next ss*/
	    int receiveSockfd = requestFile(nextSS->ip, nextSS->port, newByteArray, byteArraySize);
		
		/*receive the returning file size and allocate space for it. */
		byte ul[4];
		int urlFileSize;
		if( (numbytes = recv(receiveSockfd, ul, 4, 0))){
			urlFileSize = (int)( ((ul[3]<<24)&0xFF000000) + ((ul[2]<<16)&0x00FF0000) + ((ul[1]<<8)&0x0000FF00) + ul[0] );
		}
		else{
			if(debug)printf("data not received\n");
		}
		
		free(nextSS);
		
		int totalByteArraySize  =urlFileSize+4;
		byte fileByteArray[totalByteArraySize];
		fileByteArray[0] = ul[0];
		fileByteArray[1] = ul[1];
		fileByteArray[2] = ul[2];
		fileByteArray[3] = ul[3];
		
		receiveFile(receiveSockfd, fileByteArray, urlFileSize);
		printf("  Relaying file ...\n");
		returnFile(requestSockfd, fileByteArray, totalByteArraySize);
	  }
	  sleep(2);
	  close(requestSockfd);
	  printf("  Goodbye!\n");
	  pthread_exit(NULL);
  }

/** decrement the number of stepping stones left in the file portion of the byte array */

void decrementSSNum(byte * byteArray){
	int ssNumStart = (packLength)byteArray[0]+4;
	int ssNumEnd = ssNumStart;
		
	//find the end location for the ss number
	while((char)byteArray[ssNumEnd] != '\n' && (char)byteArray[ssNumEnd] != ' ' && (char)byteArray[ssNumEnd] != '\t') {
		++ssNumEnd;
	}
	//put the ss Number into a char array
	int numLen = ssNumEnd-ssNumStart;
	char ssChars[numLen];
	int index = 0;
	for(int i=ssNumStart;i<ssNumEnd;i++){
		ssChars[index++] = byteArray[i];
	}
	ssChars[numLen] = '\0';
	//decrement ssNum and put back in byteArray
	int num;
	num = atoi(ssChars);
	if(debug)printf("SS Num %d\n", num);
	--num;
	int newlength = sprintf(ssChars,"%d",num);
	ssChars[newlength] = '\0';
	
	index = 0;
	//put in the port number with ' ''s if less digits
	for(int i=ssNumStart;i<ssNumEnd;i++){
		if(i>=ssNumStart+newlength){
			byteArray[i] = ' ';
		}
		else{
			byteArray[i] = ssChars[index++];
		}
	}
	if(debug){printf("after Decrement:\n");printByteArray(byteArray);}
}
  
/** extract the Port from the byteArray and store in nextSS->port*/
void extractPort(struct ipPortPair *nextSS, byte * byteArray, int startIndex){
	//find the start and end of the port number
	int endIndex;
	int totalSize = (packLength)byteArray[0] + (packLength)byteArray[2] + 4;
	
	while((char)byteArray[startIndex] == ' ' || (char)byteArray[startIndex] == '\t'){
		++startIndex;
	}
	endIndex = startIndex;
	while((char)byteArray[endIndex] != '\n' && (char)byteArray[endIndex] != ' ' 
		&& (char)byteArray[endIndex] != '\t' && (char)byteArray[endIndex] != '\0'
		&& (endIndex < totalSize) ){
		++endIndex;
	}
	
	//save port number into nextSS->port
	char port[endIndex-startIndex];
	int index = 0;
	for(int i=startIndex;i<endIndex;i++){
		port[index++] = byteArray[i];
		byteArray[i] = ' ';
	}
	byteArray[endIndex] = ' ';

	port[endIndex-startIndex] = '\0';
	nextSS->port = atoi(port);
}

/** extract the ip address from the byteArray and store in nextSS->ip*/
int extractIPAddress(struct ipPortPair * nextSS, byte * byteArray, int randomSS){
	packLength URL_LEN = (packLength)byteArray[0];
	//packLength totalSize = URL_LEN + (packLength)byteArray[2] + 4;
	int startIndex = 4+URL_LEN;
	int endIndex = 4+URL_LEN;

		//extract the next ss location in the array
	for(;randomSS >0;--randomSS){
		while((char)byteArray[startIndex] != '\n'){ 
			++startIndex;
		}
		++startIndex;
	}
	endIndex = startIndex;
	while((char)byteArray[endIndex] != ','){
		++endIndex;
	}

	int index = 0;
	for(int i=startIndex;i<endIndex;i++){
		nextSS->ip[index++] = byteArray[i];
		byteArray[i] = ' ';
	}
	nextSS->ip[index] = '\0';
	byteArray[endIndex] = ' ';
	return startIndex;
}


  /** *****Initialize the TCP connection and returns the socket File Descriptor ****/

int initializeConnection(char * port){
      int sockfd, rv, fdmax;   // socket File Descriptor, error value, maximum file descriptor number
      struct addrinfo hints, *servinfo, *p;
      struct sigaction sa;
      int yes=1;
    
      fd_set master;    // master file descriptor list
      fd_set read_fds;  // temp file descriptor list for select()

      FD_ZERO(&master);    // clear the master and temp sets
      FD_ZERO(&read_fds);

	  
      memset(&hints, 0, sizeof hints);
      hints.ai_family = AF_UNSPEC;
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_flags = AI_PASSIVE; // use my IP

      if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) {
	  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
	  freeaddrinfo(servinfo);
	  return 1;
      }

      // loop through all the results and bind to the first we can
      for(p = servinfo; p != NULL; p = p->ai_next) {
	  if ((sockfd = socket(p->ai_family, p->ai_socktype,
		  p->ai_protocol)) == -1) {
	      perror("server: socket");
	      continue;
	  }

      freeaddrinfo(servinfo); // frees the memory that was allocated for servinfo
	  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
		  sizeof(int)) == -1) {
	      perror("SS1: setsockopt");
	      exit(1);
	  }

	  if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
	      close(sockfd);
	      perror("SS2: bind");
	      continue;
	  }

	  break;
      }

      //if failed to bind
      if (p == NULL)  {
	  fprintf(stderr, "SS3: failed to bind\n");
	  return 2;
      }


      if (listen(sockfd, BACKLOG) == -1) { // if there was an error listening;
	  perror("SS4: Listen");                // state the error was in Listen;
	  exit(1);                         // & Quit 
      }
      
      // add the listener to the master set
      FD_SET(sockfd, &master);

      // keep track of the biggest file descriptor
      fdmax = sockfd; // so far, it's this one

      sa.sa_handler = sigchld_handler; // reap all dead processes
      sigemptyset(&sa.sa_mask);        // initialise and empty a signal set 
      sa.sa_flags = SA_RESTART;        // set the flags to SA_Restart
      if (sigaction(SIGCHLD, &sa, NULL) == -1) {  // if the signal action failed
	  perror("SS5: sigaction");                    // let it be known that sigaction was the culprit!
	  exit(1);                                // & exit
      }
      
      return sockfd;
}

  /**  The Following code Opens a TCP Socket  */
int openTCPsocket(char * port){	
      int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
      
      char s[INET6_ADDRSTRLEN];
      
      struct sockaddr_storage their_addr; // connector's address information
      socklen_t sin_size;
    
	  //initialize hostname to the local host name
	  char hostname[HOSTNAMESIZE];
	  gethostname(hostname, HOSTNAMESIZE);
      
	  sockfd = initializeConnection(port); //first connection made
      


  //******** Listen and wait for connections*********************************
	  int rc;
	  while(1) {  // main accept() loop
	    sin_size = sizeof their_addr;
	    if(debug)printf("%s running on port %s\n", hostname,port);
	    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); //accept a connection and store incoming address
	    if (new_fd == -1) {
	      perror("SS6: accept failed on new connection");
	      continue;
	    }
	    if(debug)printf("Accepted a connection\n");
	  
	    pthread_t pid;

	    inet_ntop(their_addr.ss_family,
	      get_in_addr((struct sockaddr *)&their_addr),
	      s, sizeof s);
	    //printf("server: got connection from %s\n", s);
		  
	    rc = pthread_create(&pid, NULL, listenAndWait, (void *)new_fd);
	    if (rc){
	      printf("ERROR; pthread_create():  %d\n", rc);
	      exit(-1);
	    }
	  }
	  return 0;
}

void returnFile(int sockfd, byte * byteArray, int totalSize){
	if(debug)printf("returning file to requester\n");
	if(debug > 2)printFileByteArray(byteArray);
	int bytes_sent;
	if ((bytes_sent = send(sockfd, byteArray, totalSize, 0)) == -1){// if there was an error listening;
		perror("send fileByteArray failed\n");// state the error was in Listen;
		exit(1); //Quit
	}
	else{
		if(debug)printf("Returned file back to requester! %d bytes\n", bytes_sent);
	}
}

void receiveFile(int sockfd, byte * byteArray, int urlFileSize){
	int offset = 4;
	int numbytes;
	//receive the URL and file into the byte array
	if(debug)printf("receiving file of size %d\n", urlFileSize);
	printf("  waiting for file...\n..\n");
	while( (numbytes = recv(sockfd, byteArray+offset, urlFileSize, 0)) > 0 ) {
		if(debug)printf("received %d bytes\n",numbytes);
		if(numbytes >= urlFileSize)break;
		offset += numbytes;
		urlFileSize -= numbytes;
	}
	if(debug > 1){
		printf("received this file:");
		printFileByteArray(byteArray);
	}
	
}

int requestFile(char *hostname, int p, byte byteArray[], int size) {
	int sockfd;
	char port[7];
	sprintf(port, "%d", p);
	port[6] = '\0';
	sockfd = initializeNewConnection(hostname, port);
	
	struct timeval tv; //struct holding microseconds and seconds for timeout with select
	tv.tv_sec = 1; //seconds
	tv.tv_usec = 0; //microseconds
	//fd_set readset; //file descriptor ready to read
	
	int bytes_sent;
	//int myIPLength = sizeof(hostname);
	
	int myNameLength = 20;
	char myHostName[myNameLength];
	
	if ((bytes_sent = send(sockfd, byteArray, size, 0)) == -1){// if there was an error listening;
		perror("send struct failed sending from:\n");// state the error was in Listen;
		for(int i=0; myNameLength > 0; ++i, --myNameLength) {
		 printf("%c", (char)myHostName[i]);
		}
		exit(1); //Quit
	}
	else{
		//printf("Sent number to server %s:%s via TCP\n",hostname, port);
	}
	return sockfd;
}

/**Creates a connection with the next ss that was chosen.
*/
int initializeNewConnection(char* hostname, char* port) {
	struct addrinfo hints, *servinfo, *p;

	memset(&hints, 0, sizeof hints); // make sure the struct is empty
	hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
	hints.ai_socktype = SOCK_STREAM; // TCP stream sockets

	//printf("host: %s, port: %s\n", hostname, port);

	int status;
	if((status = getaddrinfo(hostname, port, &hints, &servinfo)) != 0) {
	fprintf(stderr, "getaddrinfo error %d: %s\n",status, gai_strerror(status));
	freeaddrinfo(servinfo);
	exit(1);
	}

	int sockfd;

	// loop through all the results and connect to the first we can
	for(p = servinfo; p != NULL; p = p->ai_next) {
		//The new socket descriptor to be used in subsequent calls, or -1 on error 
		if ((sockfd = socket(p->ai_family, p->ai_socktype,
				p->ai_protocol)) == -1) {
			perror("client: socket");
			continue;
		}

		if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("client: connect");
			continue;
		}

		break;
	}
	freeaddrinfo(servinfo);
	return sockfd;
}

//fileName was a bad choice for a variable
//This is really the file being requested.
FILE* getFile(char* fileName){
	//Use wget to retrive file.
	//wget by default stores the file to 'requested_file'
	//Use system("wget -O outputFileName fileBeingRequested") to get the file to disk
	
	char *command =(char*) malloc(sizeof(char)*100);
	command[99] = '\0';
	strcpy(command, "wget -q -O requested_file ");
	//printf("Command: %s\n",command);
	strcat(command,fileName);
	//printf("Command: %s\n",command);
	
	system(command);
	//hopefully we have the file, cross your fingers...
	FILE* file = fopen("requested_file", "r");
	free(command);
	return file;
}

int getRandomNumber(int entries) {
	srand ( time(NULL) );//Seed the random number generator
	int retVal = rand() % entries;
	++retVal;
	return retVal;
}

void printByteArray(byte* byteArray){
	packLength URL_LEN = (packLength)byteArray[0];
	packLength filesize = (packLength)byteArray[2];
	int totalSize = URL_LEN + filesize + 4;
	printf("the byteArray (%d Bytes)\n", totalSize);
	printf("URL size: %d\n",URL_LEN);
	for(int i=4;i<URL_LEN+4;i++){
		printf("%c",(char)byteArray[i]);
	}
	printf("\nfilesize: %d\n------------------\n",filesize);
	for(int i=4+URL_LEN;i<totalSize;i++){
		printf("%c",(char)byteArray[i]);
	}
	printf("\n------------------\n");
}

void printFileByteArray(byte* byteArray){
	int filesize = (int)( ((byteArray[3]<<24)&0xFF000000) + ((byteArray[2]<<16)&0x00FF0000) + ((byteArray[1]<<8)&0x0000FF00) + byteArray[0] );
	int totalSize = filesize + 4;
	printf("the byteArray (%d Bytes)\n", totalSize);
	printf("File size: %d\n",filesize);
	printf("------------------\n");
	for(int i=4;i<filesize+4;i++){
		printf("%c",(char)byteArray[i]);
	}
	printf("\n------------------\n");
}

void printChainList(byte * byteArray, int totalSize, int URL_LEN){
	printf("  chainlist is\n  ");
	int index = URL_LEN +4;
	while((char)byteArray[index] != '\n'){
		++index;
	}
	while(index < totalSize-1){
		if((char)byteArray[index+1] == '\n' && (index+1) == (totalSize -1))break;
		printf("%c",byteArray[++index]);
		if((char)byteArray[index+1] == ',' && (char)byteArray[index+2] != ' ')
			printf(" ");
		if((char)byteArray[index] == '\n')
			printf("  ");
	}
	printf("\n");
}

void printRequestedFile(byte *byteArray){
	packLength URL_LEN = (packLength)byteArray[0];
	printf("  Request: ");
	for(int i=4;i<URL_LEN+4;i++){
		printf("%c", (char)byteArray[i]);
	}
	printf("\n");
}
 
void printHostIPAddress(){
	char szHostName[128];

	if( gethostname(szHostName, 128) == 0 )
	{
		// Get host adresses
		struct hostent * pHost;
	
		pHost = gethostbyname(szHostName);
	// Part 7 (optional) Illustrates the internal format of an IP address
	char * addr=pHost->h_addr;
	printf("%d", (unsigned char)addr[0]);
	for (int i=1; i<4; i+=1)
		printf(".%d", (unsigned char)addr[i]);
	}
}

/** MAIN DRIVER FOR THE SS */

int main(int argc, char *argv[]){
	  opterr = 0; // option error
	  
	  char defaultPort[5];
	  strcpy(defaultPort,"3490\0");//default if no port specified
	  int portnum; // given port number
	  char * port_char; //char representation of given port
	  int c; // current option
	  int pflag = 0; //p has been used yet
	  
	  //parse all command line options
	  while ((c = getopt (argc, argv, "p:")) != -1){
	  switch (c)
	    {
		  //option -p
			  case 'p':
			  if (pflag==1){cout<<"Double argument -p detected. Quitting." << endl; exit(0);} 

				  port_char = optarg;
				  portnum = atoi (port_char);
				  pflag = 1;
			  //port num must be between 1024 and 65535
			  if ( portnum <= 1023  || portnum > 65535){cout<<"Not a valid port number. Quitting."<<endl; exit(0);}
			  break;

				  default: cout<<" Unknown argument: only -p [port] allowed. Quitting."<<endl; exit(0);
			  break; 
	    }
	  }
	  
	  //set port to default setting
	  if(!pflag){ 
	    port_char = defaultPort;
	  }
	 
	 //print host ip and port
	 printf("ss: ");
	 printHostIPAddress();
	 printf(", %s\n", port_char);
	  
	  //open TCP socket and listen for incoming connections
	  openTCPsocket(port_char);
  }
